package booking

import (
	"car-thirdparty-api/internal/dao"
	"car-thirdparty-api/internal/model"
	"car-thirdparty-api/internal/model/entity"
	"car-thirdparty-api/library/liberr"
	"context"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
)

func (c *LogicV1) BookingAccess(ctx context.Context, req *model.BookingAccessReq) (res *model.BookingAccessRes, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		// 查询用户是否存在
		var userInfo *entity.SysUser
		err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().UserName+" = ?", req.UserId).Scan(&userInfo)
		liberr.ErrIsNil(ctx, err, "用户信息查询失败")
		if userInfo == nil {
			// 返回错误结果
			g.Log().Error(ctx, "用户不存在，用户登录名为", req.UserId)
			err = gerror.NewCode(UserNotExistErrCode)
		}
		liberr.ErrIsNil(ctx, err)

		// 获取管理员账号，判断是否为超级管理员
		var account *entity.SysConfig
		err = dao.SysConfig.Ctx(ctx).Where(dao.SysConfig.Columns().ConfigKey+" = ?", "super.admin.account").Scan(&account)
		liberr.ErrIsNil(ctx, err, "超级管理员账号查询失败")
		if account == nil {
			// 返回错误结果
			g.Log().Error(ctx, "未配置超级管理员")
			err = gerror.NewCode(SuperAdminErrCode)
		}
		liberr.ErrIsNil(ctx, err)

		// 是否为超级管理员，超级管理员具有预约权限，可以直接获取预约限制信息
		if account.ConfigValue != req.UserId {
			// 获取用户角色
			var userRole []*entity.SysUserRole
			err = dao.SysUserRole.Ctx(ctx).Where(dao.SysUserRole.Columns().UserId+" = ?", userInfo.UserId).Scan(&userRole)
			if err != nil || userRole == nil || len(userRole) <= 0 {
				// 返回错误结果
				g.Log().Error(ctx, "用户角色获取失败，用户id为", userInfo.UserId)
				err = gerror.NewCode(RoleIdErrCode)
				return
			}
			liberr.ErrIsNil(ctx, err)

			roleIds := make([]int64, 0)
			for _, v := range userRole {
				roleIds = append(roleIds, v.RoleId)
			}

			// 获取菜单id
			menuId, err := dao.SysMenu.Ctx(ctx).Where(dao.SysMenu.Columns().Perms+" = ?", "car:booking:add").Fields(dao.SysMenu.Columns().MenuId).One()
			if err != nil || menuId.IsEmpty() {
				// 返回错误结果
				g.Log().Error(ctx, "菜单id获取失败，菜单权限为", "car:booking:create")
				err = gerror.NewCode(MenuIdErrCode)
			}
			liberr.ErrIsNil(ctx, err)

			// 查询角色是否拥有预约权限
			var roleMenu []*entity.SysRoleMenu
			err = dao.SysRoleMenu.Ctx(ctx).Where(dao.SysRoleMenu.Columns().MenuId+" = ?", menuId["menu_id"].Int()).Where(dao.SysRoleMenu.Columns().RoleId+" IN (?)", roleIds).Scan(&roleMenu)
			if err != nil || roleMenu == nil || len(roleMenu) <= 0 {
				// 返回错误结果
				g.Log().Error(ctx, "角色菜单权限获取失败，角色id列表为", roleIds)
				err = gerror.NewCode(RoleMenuErrCode)
			}
			liberr.ErrIsNil(ctx, err)
		}

		// 获取用户预约次数限制
		var bookingLimit *entity.BookingLimit
		err = dao.BookingLimit.Ctx(ctx).Where(dao.BookingLimit.Columns().SysUser+" = ?", userInfo.UserId).Scan(&bookingLimit)
		liberr.ErrIsNil(ctx, err, "用户预约限制信息查询失败")
		if bookingLimit == nil {
			// 返回错误结果
			g.Log().Error(ctx, "无预约限制信息，用户登录名为", req.UserId)
			err = gerror.NewCode(NoAuthErrCode)
			return
		}
		liberr.ErrIsNil(ctx, err)
		if bookingLimit.LimitTime <= 0 {
			// 返回次数不足的错误
			g.Log().Error(ctx, "可用预约次数不足，用户登录名为", req.UserId)
			err = gerror.NewCode(NoLimitErrCode)
		}
		liberr.ErrIsNil(ctx, err)

		//返回正常数据数据
		res = &model.BookingAccessRes{
			BookingLimit: bookingLimit.LimitTime,
			MaxDays:      bookingLimit.MaxDays,
		}
	})

	return
}
